#include "StdAfx.h"
#include <windows.h> 
#include <afxwin.h>
#include <atlconv.h>

#include "PDAserver.h"
#include "RTIcommand.h"
#include "CallBack.h"

using namespace net;

extern void appendText(const wchar_t* text);

#define DEFAULT_BUFFER_LENGTH 512

PDAserver::PDAserver(void)
: commandSocket(INVALID_SOCKET), callbackSocket(INVALID_SOCKET)
{
	startRTIservices("3000");
	startCallBackServices("3001");
}

PDAserver::~PDAserver(void)
{
}

void PDAserver::sendCommand(RTIcommand* comm)
{
	char* raw = comm->serialize();
	send (this->commandSocket, raw, strlen (raw) + 1, 0);
}

/*
* receive callbacks from server
*/
CallBack* PDAserver::getCallBack()
{
	int nRead = 0;
	char buf[DEFAULT_BUFFER_LENGTH];
	CallBack* pcb;

	nRead = recv(this->callbackSocket, buf, 20, 0);
	
	if(nRead < 5)
	{
		pcb = NULL;
	}
	else
	{
		char* raw = (char*)malloc(sizeof(char) * strlen(buf));
		strcpy(raw, buf);
		pcb = new CallBack(raw);
	}
	return pcb;
}

int PDAserver::initConnection(SOCKET& ServerSock, SOCKADDR_IN& destination_sin)
{	
	int index = 0;                      // Integer index
	TCHAR szError[100];                 // Error message string
	
	PHOSTENT phostent = NULL;           // Points to the HOSTENT structure
	// of the server
	WSADATA WSAData;                    // Contains details of the 
	// Winsocket implementation

	// Initialize Winsocket. 
	if (WSAStartup (MAKEWORD(1,1), &WSAData) != 0) 
	{
		wsprintf (szError, TEXT("WSAStartup failed. Error: %d"), 
			WSAGetLastError ());
		MessageBox (NULL, szError, TEXT("Error"), MB_OK);
		return FALSE;
	}

	// Create a TCP/IP socket that is bound to the server.
	if ((ServerSock = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
	{
		wsprintf (szError, TEXT("Allocating socket failed. Error: %d"), 
			WSAGetLastError ());
		MessageBox (NULL, szError, TEXT("Error"), MB_OK);
		return FALSE;
	}

	// Fill out the server socket's address information.
	destination_sin.sin_family = AF_INET;

	// Retrieve the host information corresponding to the host name.
	if ((phostent = gethostbyname ("aceramd")) == NULL) 
	{
		wsprintf (szError, TEXT("Unable to get the host name. Error: %d"), 
			WSAGetLastError ());
		MessageBox (NULL, szError, TEXT("Error"), MB_OK);
		closesocket (ServerSock);
		return FALSE;
	}

	// Assign the socket IP address.
	memcpy ((char FAR *)&(destination_sin.sin_addr), 
		phostent->h_addr, 
		phostent->h_length);
}

int PDAserver::startRTIservices(char* port)
{
	int index = 0;                      // Integer index
	TCHAR szError[100];                 // Error message string

	SOCKET ServerSock = INVALID_SOCKET; // Socket bound to the server
	SOCKADDR_IN destination_sin;        // Server socket address

	initConnection(ServerSock, destination_sin);

	// Convert to network ordering.
	destination_sin.sin_port = htons (3000);   

	// Establish a connection to the server socket.
	if (connect (ServerSock, 
		(PSOCKADDR) &destination_sin, 
		sizeof (destination_sin)) == SOCKET_ERROR) 
	{
		wsprintf (szError, 
			TEXT("Connecting to the server failed. Error: %d"),
			WSAGetLastError ());
		MessageBox (NULL, szError, TEXT("Error"), MB_OK);
		closesocket (ServerSock);
		return FALSE;
	}
	this->commandSocket = ServerSock;

	appendText(L"RTIservices: connected to server");
}

int PDAserver::startCallBackServices(char* port)
{
	int index = 0;                      // Integer index
	TCHAR szError[100];                 // Error message string

	SOCKET ServerSock = INVALID_SOCKET; // Socket bound to the server
	SOCKADDR_IN destination_sin;        // Server socket address

	initConnection(ServerSock, destination_sin);

	// Convert to network ordering.
	destination_sin.sin_port = htons (3001);   

	// Establish a connection to the server socket.
	if (connect (ServerSock, 
		(PSOCKADDR) &destination_sin, 
		sizeof (destination_sin)) == SOCKET_ERROR) 
	{
		wsprintf (szError, 
			TEXT("Connecting to the server failed. Error: %d"),
			WSAGetLastError ());
		MessageBox (NULL, szError, TEXT("Error"), MB_OK);
		closesocket (ServerSock);
		return FALSE;
	}
	this->callbackSocket = ServerSock;

	appendText(L"CallBackServices: connected to server");
}
